﻿//-------------------------------------------------------------------
//	Copyright (c) 2010-2013  Zhirnov Andrey
//	This file is part of the "UX Standard Lib" project.
//	See copyright notice in "UX_STL_Ext.h".
//-------------------------------------------------------------------

#ifndef _UXS_GLES_TEXTURE_H
#define _UXS_GLES_TEXTURE_H

#include "GLESRenderBuffer.h"

namespace UX_STL
{
namespace GLESshell
{


	//
	// Sampler Source
	//

	struct GLESSamplerSrc
	{
		struct TWrap {
			gl_wrap::type	s, t, r;
			///
			TWrap(gl_wrap::type eS = gl_wrap::REPEAT,
				  gl_wrap::type eT = gl_wrap::REPEAT,
				  gl_wrap::type eR = gl_wrap::REPEAT):
				s(eS), t(eT), r(eR) {}
			
			bool operator == (const TWrap &right) const {
				return s == right.s && t == right.t && r == right.r;
			}
		};

		struct TFilter {
			gl_filter::type	min,
							mag;
			///
			TFilter(gl_filter::type eMin = gl_filter::LINEAR_MIPMAP_LINEAR,
					gl_filter::type eMag = gl_filter::LINEAR):
				min(eMin), mag(eMag) {}

			bool operator == (const TFilter &right) const {
				return min == right.min && mag == right.mag;
			}
		};

		TWrap				sWrap;			// OES_texture_3D
		TFilter				sFilter;
		gl_compare::type	eCompareRTT;	// EXT_shadow_samplers
		uint8				uAnisotropy;	// EXT_texture_filter_anisotropic
		///
		GLESSamplerSrc(): eCompareRTT(gl_compare::NONE), uAnisotropy(1) {}

		GLESSamplerSrc(const TWrap &wrap, const TFilter &filter, gl_compare::type cmp, uint8 anisotropy):
			sWrap(wrap), sFilter(filter), eCompareRTT(cmp), uAnisotropy(anisotropy) {}

		bool operator == (const GLESSamplerSrc &right) const
		{
			return ( sWrap == right.sWrap && sFilter == right.sFilter &&
					 eCompareRTT == right.eCompareRTT && uAnisotropy == right.uAnisotropy );
		}
	};



	//
	// Software Sampler
	//

	class _EXPORT_ GLESSamplerSW : public GLESBaseObject
	{
	public:
		typedef GLESSamplerSrc::TWrap	TWrap;
		typedef GLESSamplerSrc::TFilter	TFilter;

	protected:
		GLESSamplerSrc	_sSrc;

	public:
		GLESSamplerSW() {}
		~GLESSamplerSW() {}

		bool Create(const GLESSamplerSrc &sSource);
		void Destroy();

		void Bind(uint8 unit)	const;
		void Bind()				const;
		void Unbind(uint8 unit)	const;
		void Unbind()			const;

		bool Apply(const GLESTexture *pTex)	const;

		TWrap const &			Wrap()			const	{ return _sSrc.sWrap; }
		TFilter const &			Filter()		const	{ return _sSrc.sFilter; }
		gl_compare::type		CompareRTT()	const	{ return _sSrc.eCompareRTT; }
		uint8					Anisotropy()	const	{ return _sSrc.uAnisotropy; }
		GLESSamplerSrc const&	GetSource()		const	{ return _sSrc; }
	};



	//
	// Base Texture
	//

	class GLESTexture : public GLESRenderTarget
	{
	protected:
		GLuint						_uID;
		GLESSamplerSW				_cSampler;
		gl_texture::type const		_eTarget;
		uint16						_uMaxLevel;
		
	public:
		GLESTexture(gl_texture::type eTarget = gl_texture::TEXTURE_2D);
		~GLESTexture();
		
		// GLESRenderTarget //
		virtual void Attach(GLESFrameBuffer *pFBO, gl_fbo_attach::type eAttach, uint uLevel = 0);
		/*
		virtual bool Storage(gl_rt_format::type eFormat, const uvec3 &vDim, uint uLevels = 0, uint8 uSamples = 0);
		virtual bool CreateLevel(uint uLevel, gl_tex_iformat::type eIFormat = gl_tex_iformat::_UNKNOWN);
		virtual bool SetImage(gl_tex_iformat::type eIFormat, const uvec3 &vDim, gl_pixel_format::type eFormat, gl_pixel::type eType, const void *pData, uint uLevel = 0);
		virtual bool SubImage(const uvec3 &vOffset, const uvec3 &vDim, gl_pixel_format::type eFormat, gl_pixel::type eType, const void *pData, uint uLevel = 0);
		virtual bool SetCompressedImage(gl_tex_iformat::type eIFormat, const uvec3 &vDim, const void *pData, usize uDataSize, uint uLevel = 0);
		virtual bool CompressedSubImage(gl_tex_iformat::type eFormat, const uvec3 &vOffset, const uvec3 &vDim, const void *pData, usize uDataSize, uint uLevel = 0);
		virtual void Destroy();*/
		
		void Bind() const;
		void Bind(uint8 uStage) const;
		void Unbind(uint8 uStage) const;
		void Unbind() const;

		bool GenerateMipmaps() const;
		void SetBaseLevel(int iLevel) const;
		bool SetSampler(const GLESSamplerSrc &sSrc);
		bool ApplySampler(const GLESSamplerSrc &sSrc) const;
		
		GLuint					Id()					const	{ return _uID; }
		gl_texture::type		Target()				const	{ return _eTarget; }
		GLESSamplerSW const &	Sampler()				const	{ return _cSampler; }
		uvec3 const				LevelDimension(uint i)	const;
	};



	//
	// Texture 2D
	//

	class GLESTexture2D : public GLESTexture
	{
	};



	//
	// Texture Cube Map
	//

	class GLESTextureCube : public GLESTexture
	{
	};



	//
	// Texture 3D (Extension)
	//

	class GLESTexture3D : public GLESTexture
	{
	};

	
//-------------------------------------------------------------------

}	// GLESshell
}	// UX_STL

#endif	// _UXS_GLES_TEXTURE_H
